using UnityEngine;

/// <summary>
/// 第一人称角色控制器（适用于 FPS / 探索类游戏）
/// 具备：
/// - 视角控制（鼠标移动）
/// - 行走、奔跑、跳跃（基于 CharacterController ）
/// - 重力系统
/// </summary>
public class FirstPersonController : MonoBehaviour
{
    [Header("鼠标视角控制")]
    public Transform sceneCamera; // 摄像机
    public float mouseSensitivity = 200f; // 鼠标灵敏度
    public float minAngle = -70f; // 最小视角（上下）
    public float maxAngle = 70f;  // 最大视角（上下）

    private float xRotation = 0f; // 记录 X 轴旋转角度
    private CharacterController cc;

    [Header("移动参数")]
    public float walkSpeed = 4f; // 行走速度
    public float runSpeed = 8f;  // 跑步速度
    public float jumpForce = 5f; // 跳跃力度
    public float acceleration = 10f; // 角色移动加速度（防止滑动感）

    private Vector3 moveDirection; // 移动方向
    private Vector3 velocity;      // 角色垂直速度

    [Header("重力控制")]
    public float gravity = 9.81f; // 重力值
    public float groundOffset = 0.1f; // 贴地修正值
    public LayerMask groundLayer; // 地面层

    [Header("地面检测")]
    public Transform groundCheck; // 地面检测点
    public float checkRadius = 0.1f; // 地面检测范围
    private bool isGrounded; // 是否站在地面

    private void Start()
    {
        cc = GetComponent<CharacterController>();
        HideCursor(); // 启动时隐藏鼠标
    }

    private void Update()
    {
        HandleView();
        HandleMovement();
        HandleCursorControl();
    }

    /// <summary>
    /// 处理鼠标视角控制
    /// </summary>
    private void HandleView()
    {
        float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
        float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;

        xRotation -= mouseY;
        xRotation = Mathf.Clamp(xRotation, minAngle, maxAngle); // 限制上下视角

        //transform.Rotate(Vector3.up * mouseX);
        //sceneCamera.localRotation = Quaternion.Euler(xRotation, 0, 0);

        // 处理水平旋转
        Quaternion deltaRotation = Quaternion.Euler(0, mouseX, 0);
        transform.rotation *= deltaRotation; // 直接修改 rotation 避免浮点误差累积

        // 处理垂直旋转
        sceneCamera.localRotation = Quaternion.Euler(xRotation, 0, 0);
    }

    /// <summary>
    /// 处理角色移动、跳跃、重力
    /// </summary>
    private void HandleMovement()
    {
        // **地面检测（防止角色浮空）**
        isGrounded = Physics.Raycast(groundCheck.position, Vector3.down, checkRadius, groundLayer);

        if (isGrounded && velocity.y < 0)
        {
            velocity.y = -groundOffset; // 轻微向下修正，防止抖动
        }

        // **方向输入**
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");

        // **计算移动方向（归一化防止斜向加速）**
        Vector3 move = transform.right * horizontal + transform.forward * vertical;
        if (move.magnitude > 1f) move.Normalize(); // 归一化防止跑得过快

        // **确定速度（奔跑 / 行走）**
        float speed = (isGrounded && Input.GetKey(KeyCode.LeftShift)) ? runSpeed : walkSpeed;

        // **优化：增加阻尼，让移动更平滑**
        moveDirection = Vector3.Lerp(moveDirection, move * speed, acceleration * Time.deltaTime);

        // **移动角色**
        cc.Move(moveDirection * Time.deltaTime);

        // **跳跃**
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            velocity.y = jumpForce; // 直接赋值跳跃力，防止累积过多 Y 轴速度
        }

        // **重力作用**
        velocity.y -= gravity * Time.deltaTime;
        cc.Move(velocity * Time.deltaTime);
    }

    /// <summary>
    /// 处理鼠标锁定和解锁
    /// </summary>
    private void HandleCursorControl()
    {
        if (Input.GetKeyDown(KeyCode.Escape))
        {
            ShowCursor(); // 退出光标锁定
        }
        if (Input.GetMouseButtonDown(1))
        {
            HideCursor(); // 重新锁定光标
        }
    }

    /// <summary>
    /// 显示鼠标（解锁状态）
    /// </summary>
    private void ShowCursor()
    {
        Cursor.lockState = CursorLockMode.None;
        Cursor.visible = true;
    }

    /// <summary>
    /// 隐藏鼠标（锁定状态）
    /// </summary>
    private void HideCursor()
    {
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }
}
